package com.w7vm.menuweb.dao;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

public abstract class GenericDAO<T> {
	
	
	@PersistenceContext
	private EntityManager em;
	
	private Class<T> entityClass;
	
	public GenericDAO(Class<T> entityClass){
		this.entityClass = entityClass;
	}
	
	public void save(T entity){
		em.persist(entity);
	}

	public void deletePK(Object id, Class<T> classe){
		T entityToBeRemoved = em.getReference(classe, id);
		em.remove(entityToBeRemoved);
		em.flush();
	}
	
	public void delete(String namedQuery, Map<String, Object> parameters){
	        try {
	            Query query = em.createNamedQuery(namedQuery);
	 
	            // Method that will populate parameters if they are passed not null and empty
	            if (parameters != null && !parameters.isEmpty()) {
	                populateQueryParameters(query, parameters);
	            }
	 
	        } catch (Exception e) {
	            System.out.println("Error while running query: " + e.getMessage());
	            e.printStackTrace();
	        }
	 
	}
	
	public T update(T entity){
		System.out.println("Merge Update");
		em.clear();
		T t = em.merge(entity);
		em.flush();
		return t;
	}

	protected List<T> findByAll(String namedQuery) {
        List<T> result = null;
 
        try {
            Query query = em.createNamedQuery(namedQuery);
            result = query.getResultList();
 
        } catch (Exception e) {
            System.out.println("Error while running query: " + e.getMessage());
            e.printStackTrace();
        }
 
        return result;
    }

	public T find(int entityID){
		return em.find(entityClass, entityID);
	}
	
	protected T findOneResult(String namedQuery, Map<String, Object> parameters) {
        T result = null;
 
        try {
            Query query = em.createNamedQuery(namedQuery);
 
            // Method that will populate parameters if they are passed not null and empty
            if (parameters != null && !parameters.isEmpty()) {
                populateQueryParameters(query, parameters);
            }
 
            result = (T) query.getSingleResult();
 
        } catch (Exception e) {
            System.out.println("Error while running query: " + e.getMessage());
            e.printStackTrace();
        }
 
        return result;
    }
	
	protected List<T> findByCriterion(String namedQuery, Map<String, Object> parameters) {
        List<T> result = null;
 
        try {
            Query query = em.createNamedQuery(namedQuery);
 
            // Method that will populate parameters if they are passed not null and empty
            if (parameters != null && !parameters.isEmpty()) {
                populateQueryParameters(query, parameters);
            }
 
            result = query.getResultList();
 
        } catch (Exception e) {
            System.out.println("Error while running query: " + e.getMessage());
            e.printStackTrace();
        }
 
        return result;
    }

	protected List<String> findByCriterionString(String namedQuery, Map<String, Object> parameters) {
        List<String> result = null;
 
        try {
            Query query = em.createNamedQuery(namedQuery);
 
            // Method that will populate parameters if they are passed not null and empty
            if (parameters != null && !parameters.isEmpty()) {
                populateQueryParameters(query, parameters);
            }
 
            result = query.getResultList();
 
        } catch (Exception e) {
            System.out.println("Error while running query: " + e.getMessage());
            e.printStackTrace();
        }
 
        return result;
    }

	private void populateQueryParameters(Query query, Map<String, Object> parameters) {
		 
        for (Entry<String, Object> entry : parameters.entrySet()) {
            query.setParameter(entry.getKey(), entry.getValue());
        }
    }
	

}
